﻿//-------------------------------------------------------------------
//	Copyright (c) 2010-2014  Zhirnov Andrey
//	This file is part of the "UX Standard Lib" project.
//	See copyright notice in "UX_OCF_Parser.h".
//-------------------------------------------------------------------

#ifndef _UXS_META_DATA_H
#define _UXS_META_DATA_H

#pragma once

#include "CreateMetaObject.h"

namespace UX_STL
{
namespace UXMetaTypes
{
	
	class CMetaClass;
	class CMetaSetIterator;
	class CMetaStructIterator;
	class CMetaAddIterator;
	class CMetaArrayIterator;
	class CMetaVarArrayIterator;
	
	typedef void (CALLBACK *PResizeProc_t)(void *pArr, usize uNewSize, usize uElemSize);
	typedef bool (CALLBACK *PObjectConstructProc_t)(CMetaSetIterator *&pIter, TVariant &sVar, void *pParam);
	typedef bool (CALLBACK *PArrayConstructProc_t)(CMetaArrayIterator *&pIter, TVariant &sVar, void *pParam);
	

	// helper macro
#	define UX_CREATE_METACLASS( _mc, _type )			_mc.CreateExt<_type>( #_type )
#	define UX_CREATE_METACLASS_EXT( _mc, _type, _ns )	_mc.CreateExt<_type>( #_type, _type(), _ns )
#	define UX_ADDFIELD( _iter, _field )					_iter->AddField( _field, StringUtils::ToMetaFieldName( #_field ).cstr() )



	//
	// Meta Data Value Type
	//

	namespace e_value
	{
		enum	type	: uint8
		{
			UNKNOWN		= 0,
			BOOL		= 1,
			INT8		= 2,
			INT16		= 3,
			INT32		= 4,
			INT64		= 5,
			FLOAT		= 6,
			DOUBLE		= 7,
			STRING		= 8,
			OBJECT		= 9,		// class, struct
			ARRAY		= 10,		// array
			CUSTOM		= 11,		// user define type
			BIN_ARRAY	= 12,		// binary array, use simple types: int32, float, (TODO: int64, double)
			VAR_ARRAY	= 13,		// variant array (any type array)
		};
	}

	
	//
	// Meta Data Base Type
	//

	class UX_EXPORT IMetaBaseType
	{
	protected:
		string				_sName;
		usize				_uSize;
		uint				_uOffset;
		e_value::type const	_eType;

	public:
		IMetaBaseType(uni_c_string pName, uint uOffset, usize uSize, e_value::type eType);
		virtual ~IMetaBaseType() {}

		uint			GetSize()	const	{ return _uSize; }
		uint			GetOffset()	const	{ return _uOffset; }
		e_value::type	GetType()	const	{ return _eType; }
		const string &	GetName()	const	{ return _sName; }

		virtual bool SetValue(void *pObj, const void * const pValue, e_value::type eType) const;
		virtual bool GetValue(void *pObj, void * pValue, e_value::type eType) const;
		virtual bool GetValue(void *pObj, string &sValue) const;
		virtual bool AddField(const void *pObj, const void *pField, uni_c_string pName, e_value::type eType);
		virtual bool GetField(uni_c_string sName, IMetaBaseType *&pField) const;
		virtual bool GetField(uint uNumb, IMetaBaseType *&pField);
	};
	


	//
	// Meta Data Custom Object Interface
	//

	class IMetaCustomObject
	{
	public:
		virtual bool SetValue(void *pObj, const void * const pValue, e_value::type eType) = 0;
		virtual bool GetValue(void *pObj, void * pValue, e_value::type eType) = 0;
		virtual bool GetValue(void *pObj, string &sValue) = 0;
		virtual bool AddField(const void *pObj, const void *pField, uni_c_string pName, e_value::type eType) = 0;
		virtual bool GetField(uni_c_string sName, IMetaBaseType *&pField) = 0;
		virtual bool GetField(uint uNumb, IMetaBaseType *&pField) = 0;
		virtual void Free() = 0;
	};



	//
	//	Meta Data Default Type
	//

	template <typename T, e_value::type E>
	class UX_EXPORT CMetaDefType : public IMetaBaseType
	{
		friend class CMetaUtils;

	private:
		CMetaDefType(const CMetaDefType &cObj);
		virtual ~CMetaDefType();

		void _SetValue(void *pObj, T tValue)  const;
		void _GetValue(void *pObj, T &tValue) const;

	public:
		CMetaDefType(uni_c_string pName, uint uOffset);

		virtual bool SetValue(void *pObj, const void * const pValue, e_value::type eType) const;
		virtual bool GetValue(void *pObj, void * pValue, e_value::type eType) const;
		virtual bool GetValue(void *pObj, string &sValue) const;
	};

	
	typedef	CMetaDefType< bool,   e_value::BOOL   >		CMetaBoolType;
	typedef	CMetaDefType< int8,   e_value::INT8   >		CMetaInt8Type;
	typedef	CMetaDefType< int16,  e_value::INT16  >		CMetaInt16Type;
	typedef	CMetaDefType< int32,  e_value::INT32  >		CMetaInt32Type;
	typedef	CMetaDefType< int64,  e_value::INT64  >		CMetaInt64Type;
	typedef	CMetaDefType< float,  e_value::FLOAT  >		CMetaFloatType;
	typedef	CMetaDefType< double, e_value::DOUBLE >		CMetaDoubleType;



	//
	// Meta Data String Type
	//

	class UX_EXPORT CMetaStringType : public IMetaBaseType
	{
		friend class CMetaUtils;

	private:
		CMetaStringType(const CMetaStringType &cObj);
		virtual ~CMetaStringType();

	public:
		CMetaStringType(uni_c_string pName, uint uOffset);

		virtual bool SetValue(void *pObj, const void * const pValue, e_value::type eType) const;
		virtual bool GetValue(void *pObj, void * pValue, e_value::type eType) const;
		virtual bool GetValue(void *pObj, string &sValue) const;
	};



	//
	// Meta Data Variant Type
	//
	/*
	class UX_EXPORT CMetaVariantType : public IMetaBaseType
	{
		friend class CMetaUtils;

	private:
		CMetaVariantType(const CMetaVariantType &cObj);
		virtual ~CMetaVariantType();

	public:
		CMetaVariantType(uni_c_string pName, uint uOffset);

		virtual bool SetValue(void *pObj, const void * const pValue, e_value::type eType) const;
		virtual bool GetValue(void *pObj, void * pValue, e_value::type eType) const;
		virtual bool GetValue(void *pObj, string &sValue) const;
	};
	*/


	//
	// Meta Data Array Type
	//

	class UX_EXPORT CMetaArrayType : public IMetaBaseType
	{
		friend class CMetaUtils;
		friend class CMetaObject;
		friend class CMetaArrayIterator;

	private:
		uint					_uElemSize;		// element size with align
		Ptr< IMetaBaseType >	_pElemType;

		PResizeProc_t			_pResizeProc;


		CMetaArrayType(const CMetaArrayType &cObj);
		virtual ~CMetaArrayType();

	public:
		CMetaArrayType(uni_c_string pName, uint uOffset, uint uSize, IMetaBaseType *pType);

		bool SetProcs(PResizeProc_t pResize);
		bool GetIterator(CMetaArrayIterator *&pIter, void *pObj);
	};



	//
	// Meta Array Iterator
	//

	class UX_EXPORT CMetaArrayIterator
	{
	private:
		struct arrayDummy
		{
			void *	pMemory;
			uint	uCount,
					uSize;
		};

		Ptr< CMetaArrayType	 >	_pType;
		Ptr< const arrayDummy >	_pArr;
		uint					_uNumb;

	public:
		CMetaArrayIterator(CMetaArrayType *pMtArr, void *pObj);
		CMetaArrayIterator(const CMetaArrayIterator &iter);
		~CMetaArrayIterator();
		
		void Free();

		CMetaArrayIterator & operator = (const CMetaArrayIterator &right);
		
		CMetaArrayType *	GetArrayType()	const	{ return _pType; }
		e_value::type		GetElemType()	const	{ return _pType->_pElemType->GetType(); }

		bool SelectElem(uint uNumb);
		bool Resize(uint uNewSize);
		uint GetCurNumb()			const	{ return _uNumb; }
		uint GetCount()				const	{ return _pArr->uCount; }

		bool SetValue(uni_c_string sName, const void *pData, e_value::type eType) const;
		bool SetValue(const void *pData, e_value::type eType) const;
		
		// for values only //
		bool GetValue(void *pValue, e_value::type eType) const;
		bool GetValue(string &sValue)					 const;

		// for objects only //
		bool GetValue(uni_c_string sName, void *pValue, e_value::type eType) const;
		bool GetValue(uint uFieldNumb, void *pValue, e_value::type eType) const;
		bool GetValue(uni_c_string sName, string &sValue) const;
		bool GetValue(uint uFieldNumb, string &sValue) const;

		bool GetSetIterator(CMetaSetIterator *&pIter)		const;
		bool GetArrIterator(CMetaArrayIterator *&pIter)		const;
		bool GetStrIterator(CMetaStructIterator *&pIter)	const;
		bool GetVarIterator(CMetaVarArrayIterator *&pIter)	const;
	};


	//
	// Meta Data Variant Array Type
	//

	class UX_EXPORT CMetaVarArrayType : public IMetaBaseType
	{
		friend class CMetaUtils;
		friend class CMetaObject;
		friend class CMetaVarArrayIterator;

	private:
		CMetaVarArrayType(const CMetaVarArrayType &cObj);
		virtual ~CMetaVarArrayType();

	public:
		CMetaVarArrayType(uni_c_string pName, uint uOffset);

		bool GetIterator(CMetaVarArrayIterator *&pIter, void *pObj);
	};



	//
	// Meta Variant Array Iterator
	//

	class UX_EXPORT CMetaVarArrayIterator
	{
	private:
		typedef array< Ptr< IMetaBaseType > >	meta_array_t;

		meta_array_t				_aTypes;
		Ptr< CMetaVarArrayType >	_pType;
		Ptr< variant_array_t >		_pArr;
		uint						_uNumb;

	public:
		CMetaVarArrayIterator(CMetaVarArrayType *pMtArr, void *pObj);
		CMetaVarArrayIterator(const CMetaVarArrayIterator &iter);
		~CMetaVarArrayIterator();
		
		void Free();

		CMetaVarArrayIterator & operator = (const CMetaVarArrayIterator &right);

		bool SelectElem(uint uNumb);
		bool Resize(uint uNewSize);
		uint GetCurNumb()			const	{ return _uNumb; }
		uint GetCount()				const	{ return _pArr->Count(); }

		bool SetValue(uni_c_string sName, const void *pData, e_value::type eType) const;
		bool SetValue(const void *pData, e_value::type eType) const;
		
		bool GetSetIterator(uni_c_string sTypeName, CMetaSetIterator *&pIter);
		bool GetArrIterator(uni_c_string sTypeName, CMetaArrayIterator *&pIter);
		bool GetStrIterator(CMetaStructIterator *&pIter);
		bool GetVarIterator(CMetaVarArrayIterator *&pIter);
	};



	//
	// Meta Data Struct Type
	//

	class UX_EXPORT CMetaStructType : public IMetaBaseType
	{
		friend class CMetaUtils;
		friend class CMetaObject;
		friend class CMetaArrayIterator;

	private:
		PResizeProc_t	_pResizeProc;
		uint8			_uAlign;


		CMetaStructType(const CMetaStructType &cObj);
		virtual ~CMetaStructType();

	public:
		CMetaStructType(uni_c_string pName, uint uOffset);

		uint8 GetAlign()	const		{ return _uAlign; }

		bool SetProcs(PResizeProc_t pResize);
		bool GetIterator(CMetaStructIterator *&pIter, void *pObj);
	};



	//
	// Meta Struct Iterator
	//

	class UX_EXPORT CMetaStructIterator
	{
	private:
		struct arrayDummy
		{
			void *	pMemory;
			uint	uCount,
					uSize;
		};

		Ptr< CMetaStructType >	_pType;
		Ptr< arrayDummy		 >	_pArr;
		uint					_uPos;			// pos in binary array

	public:
		CMetaStructIterator(CMetaStructType *pMtStr, void *pObj);
		CMetaStructIterator(const CMetaStructIterator &iter);
		~CMetaStructIterator();
		
		void Free();

		CMetaStructIterator & operator = (const CMetaStructIterator &right);
		
		e_value::type		 GetElemType()	const	{ return e_value::UNKNOWN; }

		bool PushBackValue(const void *pData, e_value::type eType);
	};



	//
	// Meta Data Custom Type
	//

	class UX_EXPORT CMetaCustomType : public IMetaBaseType
	{
		friend class CMetaUtils;

	private:
		string						_sName;
		Ptr< IMetaCustomObject >	_pObj;

		CMetaCustomType(const CMetaCustomType &cObj);
		CMetaCustomType(uni_c_string pName, uint uOffset, uint uSize);
		virtual ~CMetaCustomType();

	public:
		virtual bool SetValue(void *pObj, const void * const pValue, e_value::type eType) const;
		
		virtual bool GetValue(void *pObj, void * pValue, e_value::type eType) const;
		virtual bool GetValue(void *pObj, string &sValue) const;
		
		virtual bool GetField(uni_c_string sName, IMetaBaseType *&pField) const;
		virtual bool GetField(uint uNumb, IMetaBaseType *&pField);
		
		bool SetProc(IMetaCustomObject *pObj);
	};



	//
	// Meta Data Object interface
	//

	class UX_EXPORT IMetaObject
	{
	private:
		string					_sTypeName;				// type name
		uni_c_string_array_t	_sNamespaces;

	public:
		IMetaObject(string &sName);
		IMetaObject(uni_c_string pName);
		virtual ~IMetaObject() {}

		const string &					GetTypeName()		const	{ return _sTypeName; }
		const uni_c_string_array_t &	GetFullTypeName()	const	{ return _sNamespaces; }

		virtual CMetaObject	*	GetMetaObject() = 0;
		virtual CMetaObject	*	GetNamespace() = 0;
		virtual bool			IsObject()		const	{ return false; }
	};



	//
	// Meta Data Object
	//

	class UX_EXPORT CMetaObject : public IMetaObject
	{
		friend class CMetaUtils;
		friend class CMetaClass;
		friend class CMetaObjectType;
		friend class CMetaAddIterator;
		
	private:
		typedef array< Ptr< IMetaObject > >		metaobj_array_t;
		typedef array< Ptr< IMetaBaseType > >	metabase_array_t;

	private:
		Ptr< CMetaObject >		_pNamespace;
		metaobj_array_t			_aTypes;	// types in this namespace
		metabase_array_t		_aFields;
		PObjectConstructProc_t	_pCreateObjectProc;
		PArrayConstructProc_t	_pCreateArrayProc;
		void *					_pParameter;
		uint					_uSize;

		CMetaObject(const CMetaObject &cObj, uni_c_string pName, uint uSize = 0);
		CMetaObject(CMetaObject *pNS, uni_c_string pName, uint uSize);
		CMetaObject(CMetaObject *pNS, string &sName, uint uSize);

		bool _CopyFields(const CMetaObject &cObj);

	public:
		virtual ~CMetaObject();

		uint			GetSize()		const	{ return _uSize; }
		CMetaObject	*	GetMetaObject()			{ return this; }
		CMetaObject	*	GetNamespace()			{ return _pNamespace; }
		bool			IsObject()		const	{ return true; }

		void AddToNamespace(IMetaObject *pType);
		void RemoveFromNamespace(IMetaObject *pType);

		void AddField(IMetaBaseType *pField)	{ ASSUME( pField != null );  _aFields.PushBack( pField ); }

		bool GetField(uni_c_string sName, IMetaBaseType *&pField) const;
		bool GetField(uint uNumb, IMetaBaseType *&pField);
		bool GetObj(uni_c_string sName, IMetaBaseType *&pObj, uint &uOffset) const;
		
		void SetConstructorProcs(PObjectConstructProc_t pObj, PArrayConstructProc_t pArr, void *pParam)	{ _pCreateObjectProc = pObj;  _pCreateArrayProc = pArr;  _pParameter = pParam; }
		
		bool CreateObject(CMetaSetIterator *&pIter, TVariant &sVar);
		bool CreateObjectArray(CMetaArrayIterator *&pIter, TVariant &sVar);
	};



	//
	// Meta Data Typedef
	//
	
	class UX_EXPORT CMetaTypedef : public IMetaObject
	{
		friend class CMetaUtils;

	private:
		Ptr< CMetaObject >	_pNamespace;
		Ptr< CMetaObject >	_pType;

		CMetaTypedef(CMetaObject *pNS, uni_c_string pName, CMetaObject *pObj):
			IMetaObject(pName), _pNamespace(pNS), _pType(pObj) {}

	public:
		~CMetaTypedef()	{}

		CMetaObject	*	GetMetaObject()		{ return _pType; }
		CMetaObject	*	GetNamespace()		{ return _pNamespace; }
	};



	//
	// Meta Data Object Type
	//

	class UX_EXPORT CMetaObjectType : public IMetaBaseType
	{
		friend class CMetaUtils;
		friend class CMetaObject;
		friend class CMetaClass;

	private:
		Ptr< CMetaObject >		_pType;
		
		CMetaObjectType(const CMetaObjectType &cObj);
		virtual ~CMetaObjectType();

	public:
		CMetaObjectType(uni_c_string pName, uint uOffset, CMetaObject *pObj);

		virtual bool GetField(uni_c_string sName, IMetaBaseType *&pField) const;
		virtual bool GetField(uint uNumb, IMetaBaseType *&pField);
		CMetaObject *GetObj()	const	{ return _pType; }
	};



	//
	// Meta Data Utils
	//

	class CMetaUtils
	{
	public:
		template <typename T, e_value::type E>
		static bool ConvertValue(const void * const pValue, e_value::type eType, T &tRes);
		
		template <typename T, e_value::type E>
		static bool ConvertValue(const T &tValue, e_value::type eType, void *pRes);
		
		static bool _FindObject(uni_c_string sTypeName, CMetaObject *&pObj);
		static bool Create(uni_c_string sTypeName, CMetaSetIterator *&pIter, TVariant &sVar);
		static bool CreateArray(uni_c_string sTypeName, CMetaArrayIterator *&pIter, TVariant &sVar);

		static bool CopyObject(IMetaBaseType *pObj, IMetaBaseType *&pNewObj);
		static bool Typedef(const CMetaClass &cObj, uni_c_string sNewTypeName, CMetaObject *pNS = null);
		static void Free(IMetaBaseType *&pObj);
	};



	//
	// Meta Data Set Value Iterator
	//

	class UX_EXPORT CMetaSetIterator
	{
		friend class CMetaClass;
		friend class CMetaArrayIterator;

	private:
		Ptr< CMetaObjectType >	_pBase;
		Ptr< IMetaBaseType >	_pCurObj;
		const void			*	_pObj;
		uint					_uOffset;
		

	public:
		CMetaSetIterator(const void *pObj, CMetaObjectType *pBase);
		CMetaSetIterator(const CMetaSetIterator &cIter, bool bIsObject = false);
		~CMetaSetIterator();

		void Free();

		CMetaSetIterator &	operator = (const CMetaSetIterator &right);
		const string	 &	GetObjTypeName() const;
		const uni_c_string_array_t & GetObjName() const;
		const void		 *	GetObjPtr()  const		{ return _pObj; }
		CMetaObjectType	 *	GetObjType() const		{ return _pBase; }
		IMetaBaseType	 *	GetCurObj()	 const		{ return _pCurObj; }
		uint				GetOffset()  const		{ return _uOffset; }

		const void		*	GetObjPtrWithOffset() const	{ return MovePointer( _pObj, _uOffset ); }

		bool FindObject(uni_c_string sName);
		bool SetValue(uni_c_string sName, const void * pValue, e_value::type eType) const;
		bool SetValue(const void *pValue, e_value::type eType) const;
		bool SetValue(uint uNumb, const void *pValue, e_value::type eType) const;
		bool GetArrayIterator(uni_c_string sName, CMetaArrayIterator *&pIter) const;
		bool GetStructIterator(uni_c_string sName, CMetaStructIterator *&pIter) const;
		bool GetVarArrayIterator(uni_c_string sName, CMetaVarArrayIterator *&pIter) const;

		bool GetValue(uni_c_string sName, const void *pValue, e_value::type eType) const;
	};



	//
	// Meta Data Add Field Iterator
	//

	class UX_EXPORT CMetaAddIterator
	{
		friend class CMetaClass;

	private:
		struct TMetaInfo
		{
			Ptr< CMetaObject >	pMtObj;
			const void		*	pClObj;
			///
			TMetaInfo(): pMtObj(null), pClObj(null) {}
			TMetaInfo(CMetaObject *mt, const void *cl): pMtObj(mt), pClObj(cl) {}
		};

		TDynStack< TMetaInfo >		_sObjStack;
		

	public:
		CMetaAddIterator();
		CMetaAddIterator(CMetaObject *pMObj, const void *pObj);
		CMetaAddIterator(const CMetaAddIterator &cIter);
		~CMetaAddIterator();

		void Free();

		CMetaAddIterator &	operator = (const CMetaAddIterator &right);

		template <typename T>
		void AddField(const T &pField, uni_c_string pName);

		void AddField(CMetaObject *pMetaObject, const void *pField, uni_c_string pName);
		
		void AddField(CMetaObject *pElemMetaClass, const void *pArrayField, uni_c_string pName,
						PResizeProc_t pResizeProc, usize uFieldSize);

		//bool AddCustom(const void *pObj, uni_c_string pName, IMetaCustomObject *pCustObj);

		bool Pop()		{ return _sObjStack.Pop(); }
	};

	
}
namespace UXTypes
{
	template <>
	struct TAutoPtrStrategy< UXMetaTypes::CMetaSetIterator >
	{
		static void Delete(UXMetaTypes::CMetaSetIterator *ptr)	{ ptr->Free(); }
	};

	template <>
	struct TAutoPtrStrategy< UXMetaTypes::CMetaAddIterator >
	{
		static void Delete(UXMetaTypes::CMetaAddIterator *ptr)	{ ptr->Free(); }
	};

	template <>
	struct TAutoPtrStrategy< UXMetaTypes::CMetaArrayIterator >
	{
		static void Delete(UXMetaTypes::CMetaArrayIterator *ptr) { ptr->Free(); }
	};

	template <>
	struct TAutoPtrStrategy< UXMetaTypes::CMetaVarArrayIterator >
	{
		static void Delete(UXMetaTypes::CMetaVarArrayIterator *ptr) { ptr->Free(); }
	};

	template <>
	struct TAutoPtrStrategy< UXMetaTypes::CMetaStructIterator >
	{
		static void Delete(UXMetaTypes::CMetaStructIterator *ptr) { ptr->Free(); }
	};

}
namespace UXMetaTypes
{

	typedef AutoPtr< CMetaSetIterator >			CMetaSetIteratorPtr;
	typedef AutoPtr< CMetaAddIterator >			CMetaAddIteratorPtr;
	typedef AutoPtr< CMetaArrayIterator >		CMetaArrayIteratorPtr;
	typedef AutoPtr< CMetaVarArrayIterator >	CMetaVarArrayIteratorPtr;
	typedef AutoPtr< CMetaStructIterator >		CMetaStructIteratorPtr;



	//
	// Meta Data Class
	//

	class UX_EXPORT CMetaClass
	{
		friend class CMetaObject;
		friend class CMetaUtils;

	private:
		Ptr< CMetaObjectType >	_pObject;
		bool					_bInit;

	private:
		CMetaClass(const CMetaClass &);

		void _CreateGlobal();

		static bool _s_Compare(CMetaObject *pNamespace, const string &sName);
		
		template <typename T>
		static bool CALLBACK _s_CreateObject(CMetaSetIterator *&pIter, TVariant &sVar, void *pParam);

		template <typename T>
		static bool CALLBACK _s_CreateArray(CMetaArrayIterator *&pIter, TVariant &sVar, void *pParam);

	public:
		CMetaClass();
		~CMetaClass();

		template <typename T>
		bool CreateExt(uni_c_string pName, const T& tType = T(), CMetaObject *pNamespace = null);

		bool Create(uni_c_string pName, usize uSize, CMetaObject *pNamespace = null);
		bool Inherit(uni_c_string sTypeName, CMetaObject *pNamespace = null);
		bool Inherit(const CMetaClass &cObj);

		void SetConstructorProcs(PObjectConstructProc_t pObj, PArrayConstructProc_t pArr, void *pParam);
		
		template <typename T>
		CMetaAddIterator *	GetAddIter(const T &sObj)	const	{ return _GetAddIter( &sObj ); }

		template <typename T>
		CMetaSetIterator *	GetSetIter(const T &sObj)	const	{ return _GetSetIter( &sObj ); }

		CMetaAddIterator *	_GetAddIter(const void *pObj) const;
		CMetaSetIterator *	_GetSetIter(const void *pObj) const;

		CMetaObjectType	 *	GetObject()					const	{ return _pObject; }
		CMetaObject		 *	GetObjectType()				const	{ return _pObject->GetObj(); }
		bool				IsInit()					const	{ return _bInit; }

		bool CreateObject(CMetaSetIterator *&pIter, TVariant &sVar);
		bool CreateObjectArray(CMetaArrayIterator *&pIter, TVariant &sVar);

		static bool s_InitBaseTypes(CMetaObject *pNS = null);
	};
	


	
// ----------------------- CMetaAddIterator ---------------------- //

	template <typename T>
	inline bool CALLBACK CMetaClass::_s_CreateObject(CMetaSetIterator *&pIter, TVariant &sVar, void *)
	{
		IMetaBaseType *	p_obj = CreateMetaObjectTempl<T>( null, 0, sizeof(T) );

		if ( p_obj == null or p_obj->GetType() != e_value::OBJECT ) {
			CMetaUtils::Free( p_obj );
			return false;
		}

		sVar  = T();
		pIter = new CMetaSetIterator( sVar.GetPtr(), (CMetaObjectType *)p_obj );
		return true;
	}
	

	template <typename T>
	inline bool CALLBACK CMetaClass::_s_CreateArray(CMetaArrayIterator *&pIter, TVariant &sVar, void *)
	{
		IMetaBaseType *	p_obj = CreateMetaObjectTempl<T>( null, 0, sizeof(T) );

		if ( p_obj == null or p_obj->GetType() != e_value::OBJECT ) {
			CMetaUtils::Free( p_obj );
			return false;
		}

		typedef typename TArrayType<T>::type	array_t;

		IMetaBaseType *	p_arr = CreateMetaArray( null, 0, array_t::s_Resize, sizeof(array_t), p_obj );

		if ( p_arr == null ) {
			CMetaUtils::Free( p_obj );
			return false;
		}

		sVar  = array_t();
		pIter = new CMetaArrayIterator( (CMetaArrayType *)p_arr, sVar.GetPtr() );
		return true;
	}


	template <typename T>
	inline bool CMetaClass::CreateExt(uni_c_string pName, const T& tType, CMetaObject *pNamespace)
	{
		if ( !Create( pName, sizeof(tType), pNamespace ) )
			return false;

		SetConstructorProcs( &_s_CreateObject<T>, &_s_CreateArray<T>, null );
		return true;
	}




// ---------------------- CMetaArrayIterator --------------------- //
	
	inline CMetaArrayIterator & CMetaArrayIterator::operator = (const CMetaArrayIterator &right)
	{
		_pType	= right._pType;
		_pArr	= right._pArr;
		_uNumb	= right._uNumb;
		return *this;

	}


	inline bool CMetaArrayIterator::SelectElem(uint uNumb)
	{
		if ( _pArr->uCount <= uNumb )
			return false;

		_uNumb = uNumb;
		return true;
	}


	inline bool CMetaArrayIterator::Resize(uint uNewSize)
	{
		_pType->_pResizeProc( (void *)_pArr.ptr(), uNewSize, _pType->_pElemType->GetSize() );
		_uNumb = 0;
		return true;
	}


	inline bool CMetaArrayIterator::SetValue(uni_c_string sName, const void *pData, e_value::type eType) const
	{
		IMetaBaseType	*temp = null;

		if ( !_pType->_pElemType->GetField( sName, temp ) )	
			return false;

		return temp->SetValue( (int8*)_pArr->pMemory + _pType->_uElemSize * _uNumb, pData, eType );
	}


	inline bool CMetaArrayIterator::SetValue(const void *pData, e_value::type eType) const
	{
		return _pType->_pElemType->SetValue( (int8*)_pArr->pMemory + _pType->_uElemSize * _uNumb, pData, eType );
	}


	inline bool CMetaArrayIterator::GetValue(void *pValue, e_value::type eType) const
	{
		return _pType->_pElemType->GetValue( (int8*)_pArr->pMemory + _pType->_uElemSize * _uNumb, pValue, eType );
	}


	inline bool CMetaArrayIterator::GetValue(string &sValue) const
	{
		return _pType->_pElemType->GetValue( (int8*)_pArr->pMemory + _pType->_uElemSize * _uNumb, sValue );
	}


	inline bool CMetaArrayIterator::GetValue(uni_c_string sName, void *pValue, e_value::type eType) const
	{
		IMetaBaseType	*temp = null;

		if ( !_pType->_pElemType->GetField( sName, temp ) )
			return false;

		return temp->GetValue( (int8*)_pArr->pMemory + _pType->_uElemSize * _uNumb, pValue, eType );
	}
	

	inline bool CMetaArrayIterator::GetValue(uint uFieldNumb, void *pValue, e_value::type eType) const
	{
		IMetaBaseType	*temp = null;

		if ( !_pType->_pElemType->GetField( uFieldNumb, temp ) )
			return false;
		
		return temp->GetValue( (int8*)_pArr->pMemory + _pType->_uElemSize * _uNumb, pValue, eType );
	}


	inline bool CMetaArrayIterator::GetValue(uni_c_string sName, string &sValue) const
	{
		IMetaBaseType	*temp = null;

		if ( !_pType->_pElemType->GetField( sName, temp ) )
			return false;

		return temp->GetValue( (int8*)_pArr->pMemory + _pType->_uElemSize * _uNumb, sValue );
	}
	

	inline bool CMetaArrayIterator::GetValue(uint uFieldNumb, string &sValue) const
	{
		IMetaBaseType	*temp = null;

		if ( !_pType->_pElemType->GetField( uFieldNumb, temp ) )
			return false;

		return temp->GetValue( (int8*)_pArr->pMemory + _pType->_uElemSize * _uNumb, sValue );
	}


	
//----------------------- CMetaVarArrayIterator ----------------------//
	
	inline CMetaVarArrayIterator & CMetaVarArrayIterator::operator = (const CMetaVarArrayIterator &right)
	{
		_pArr	= right._pArr;
		_uNumb	= right._uNumb;
		return *this;

	}


	inline bool CMetaVarArrayIterator::SelectElem(uint uNumb)
	{
		if ( _pArr->Count() <= uNumb )
			return false;

		_uNumb = uNumb;
		return true;
	}


	inline bool CMetaVarArrayIterator::Resize(uint uNewSize)
	{
		_pArr->Resize( uNewSize, false );
		_uNumb = 0;
		return true;
	}



// ----------------------- CMetaSetIterator ---------------------- //

	inline CMetaSetIterator & CMetaSetIterator::operator = (const CMetaSetIterator &right)
	{
		_pBase		= right._pBase;
		_pCurObj	= right._pCurObj;
		_pObj		= right._pObj;
		_uOffset	= right._uOffset;
		return *this;
	}
	

	inline const string & CMetaSetIterator::GetObjTypeName() const
	{
		return _pBase->GetObj()->GetTypeName();
	}


	inline const uni_c_string_array_t & CMetaSetIterator::GetObjName() const
	{
		return _pBase->GetObj()->GetFullTypeName();
	}


	inline bool CMetaSetIterator::FindObject(uni_c_string sName)
	{
		_pCurObj = _pBase;
		_uOffset = 0;
		return _pBase->GetObj()->GetObj( sName, _pCurObj, _uOffset );
	}


	inline bool CMetaSetIterator::SetValue(uni_c_string sName, const void * pValue, e_value::type eType) const
	{
		IMetaBaseType	*temp = null;

		if ( !_pCurObj->GetField( sName, temp ) )	
			return false;

		return temp->SetValue( (uint8*)_pObj + _uOffset, pValue, eType );
	}
	

	inline bool CMetaSetIterator::SetValue(const void *pValue, e_value::type eType) const
	{
		return _pCurObj->SetValue( (uint8*)_pObj + _uOffset, pValue, eType );
	}
	

	inline bool CMetaSetIterator::SetValue(uint uNumb, const void *pValue, e_value::type eType) const
	{
		IMetaBaseType	*temp = null;

		if ( !_pCurObj->GetField( uNumb, temp ) )
			return false;

		return temp->SetValue( (uint8*)_pObj + _uOffset, pValue, eType );
	}
	

	inline bool CMetaSetIterator::GetArrayIterator(uni_c_string sName, CMetaArrayIterator *&pIter) const
	{
		IMetaBaseType	*temp = null;

		if ( !_pCurObj->GetField( sName, temp ) or temp->GetType() != e_value::ARRAY )
			return false;

		return ((CMetaArrayType *)temp)->GetIterator( pIter, (uint8*)_pObj + _uOffset );
	}
	

	inline bool CMetaSetIterator::GetVarArrayIterator(uni_c_string sName, CMetaVarArrayIterator *&pIter) const
	{
		IMetaBaseType	*temp = null;

		if ( !_pCurObj->GetField( sName, temp ) or temp->GetType() != e_value::VAR_ARRAY )
			return false;

		return ((CMetaVarArrayType *)temp)->GetIterator( pIter, (uint8*)_pObj + _uOffset );
	}


	inline bool CMetaSetIterator::GetStructIterator(uni_c_string sName, CMetaStructIterator *&pIter) const
	{
		IMetaBaseType	*temp = null;

		if ( !_pCurObj->GetField( sName, temp ) or temp->GetType() != e_value::BIN_ARRAY )
			return false;

		return ((CMetaStructType *)temp)->GetIterator( pIter, (uint8*)_pObj + _uOffset );
	}



// ----------------------- CMetaAddIterator ---------------------- //

	inline CMetaAddIterator & CMetaAddIterator::operator = (const CMetaAddIterator &right)
	{
		_sObjStack = right._sObjStack;
		return *this;
	}
	

	template <typename T>
	inline void CMetaAddIterator::AddField(const T &tField, uni_c_string pName)
	{
		TMetaInfo	&	s_info	 = _sObjStack.Get();
		const void *	p_field	 = AddressOf( tField );
		const usize		u_offset = PointerOffset( p_field, s_info.pClObj );
		const usize		u_size	 = sizeof( tField );

		return s_info.pMtObj->AddField( CreateMetaObjectTempl<T>( pName, u_offset, u_size ) );
	}

	/*inline bool CMetaAddIterator::AddCustom(const void *pObj, uni_c_string pName, IMetaCustomObject *pCustObj)
	{
		TMetaInfo	&s_info	= _sObjStack.Get();
		return s_info.pMtObj->AddCustom( pName, (uint)( (uint8*)pObj - (uint8*)s_info.pClObj ), pCustObj );
	}*/
	
}	// UXMetaTypes


// --------------------------------------------------------------- //

	UX_DECLARE_META_OBJECT( UXMath::fvec2 );
	UX_DECLARE_META_OBJECT( UXMath::dvec2 );
	UX_DECLARE_META_OBJECT( UXMath::ivec2 );
	UX_DECLARE_META_OBJECT( UXMath::uvec2 );
	UX_DECLARE_META_OBJECT( UXMath::fvec3 );
	UX_DECLARE_META_OBJECT( UXMath::dvec3 );
	UX_DECLARE_META_OBJECT( UXMath::ivec3 );
	UX_DECLARE_META_OBJECT( UXMath::uvec3 );
	UX_DECLARE_META_OBJECT( UXMath::fvec4 );
	UX_DECLARE_META_OBJECT( UXMath::dvec4 );
	UX_DECLARE_META_OBJECT( UXMath::ivec4 );
	UX_DECLARE_META_OBJECT( UXMath::uvec4 );
	UX_DECLARE_META_OBJECT( UXMath::frect );
	UX_DECLARE_META_OBJECT( UXMath::drect );
	UX_DECLARE_META_OBJECT( UXMath::irect );
	UX_DECLARE_META_OBJECT( UXMath::urect );
	UX_DECLARE_META_OBJECT( UXMath::fquat );
	UX_DECLARE_META_OBJECT( UXMath::dquat );
	UX_DECLARE_META_OBJECT( UXMath::color4u );
	//UX_DECLARE_META_OBJECT( UXMathExt::transform_f );
	//UX_DECLARE_META_OBJECT( UXMathExt::transform_d );

	UX_DECLARE_META_OBJECT( string );
	UX_DECLARE_META_OBJECT( binary_array_t );
	
	UXMetaTypes::IMetaBaseType * CreateMetaArray(uni_c_string pName, usize uOffset, UXMetaTypes::PResizeProc_t pProc, usize uSize, UXMetaTypes::IMetaBaseType *pType);
	
	UX_DECLARE_META_OBJECT( UXTypesExt::variant_array_t );

	template <typename T, typename S, typename A>
	inline UXMetaTypes::IMetaBaseType * CreateMetaObject(uni_c_string pName, usize uOffset, usize uSize, array<T,S,A> &obj)
	{
		return CreateMetaArray( pName, uOffset, &obj.s_Resize, uSize,
								CreateMetaObjectTempl<T>( null, 0, sizeof(T) ) ); 
	}

//-------------------------------------------------------------------

}	// UX_STL

#endif	// _UXS_META_DATA_H